package com.mcodesal.framework;

import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.game.grid.GameStates.Game;
import com.game.grid.GameStates.Menu;

import android.content.Context;
import android.opengl.GLSurfaceView;
//import com.mcodesal.framework.GLSurfaceView;
import android.opengl.GLU;
import android.os.SystemClock;
import android.view.MotionEvent;

public class GameEngine implements GLSurfaceView.Renderer {

	public Context context;

	protected Timer gameTimer;
	protected long gameTime;

	//screen size when game is initialized.
	protected int screenSizeX;
	protected int screenSizeY;

	//boolean state flags.
	public boolean mAppPaused = true;
	public boolean drawing = false;
	private int prevTime = 0;
	protected GameState mCurrGameState;
	public enum State {
		LOADING, MENU, GAME
	}
	public State mCurrState;
	protected boolean stateChanged = true;

	
	public GameEngine(Context context) {
        this.context = context;
        mCurrState = State.LOADING;
    	gameTimer = new Timer(); //initializing game timer.
	}
	public void RequestStateChange(State state) {
		mCurrState = state;
		stateChanged = true;
	}
    public void touchEvent(MotionEvent event)
    {	
		mCurrGameState.handleTouchEvent(event);	
    }

	/*
	 * the update function, is used to calculate the time elapsed.
	 */
	public void update() {
		if(!mAppPaused) {
			if(!drawing) {
				gameTime = (int)SystemClock.uptimeMillis();
				mCurrGameState.update(gameTime);
			}
		}
	}
	
	public void doPause() {
    	this.mAppPaused = true;
    }
    public void doResume() {
    	this.mAppPaused = false;
    }
    
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		ResourceProvider.getInstance().loadGLTextures(gl, this.context);
		gl.glEnable(GL10.GL_TEXTURE_2D);            //Enable Texture Mapping
		gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
	    gl.glClearColor(0.0f, 0.0f, 0.0f, 1f);    //Black Background
	    gl.glClearDepthf(1.0f);                     //Depth Buffer Setup
	    gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
	    gl.glDepthFunc(GL10.GL_LEQUAL);  
	    gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
    }

    public void onSurfaceChanged(GL10 gl, int w, int h) {
    	if(stateChanged) {
	        stateChanged = false;
	    	switch(mCurrState) {
				case LOADING:
					mAppPaused = true;
					gl.glViewport(0, 0, w, h);
			        screenSizeX = w;
					screenSizeY = h;
					//the max height is set as the min height in order to match the
					//coordinate system to the screenspace coordinate system
			        GLU.gluOrtho2D(gl, 0f, screenSizeX, screenSizeY, 0f);
	
			    	gameTimer.schedule(new TimerTask() { public void run() { update();}}, 1, 1);
			    	mCurrState = State.MENU;
			    	stateChanged = true;
					break;
				case MENU:
					mCurrGameState = new Menu(this);
					mAppPaused = false;
					break;
				case GAME:
					mCurrGameState = new Game(this);
					mCurrGameState.initialize(gl, w, h);
					break;
	    	}
    	}
		
    }
    
    public void onDrawFrame(GL10 gl) {
    	if(stateChanged) {
    		this.onSurfaceChanged(gl, screenSizeX, screenSizeY);
    	}
	    	//Frame-locking code
	    	int time = (int)SystemClock.uptimeMillis();
	    	if (prevTime == 0) {
	            prevTime = time;
	        }
	    	
	    	int delta = time-prevTime;
	    	if(delta < 50) {
				try {
					Thread.sleep(50-delta);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
	    	prevTime = (int)SystemClock.uptimeMillis();//prevTime += 50;
	    	
	    	drawing = true;
	    	mCurrGameState.render(gl);
	    	drawing = false; //drawing ended
    }
}